package org.suwenqian.audiovideosummary.service.impl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.suwenqian.audiovideosummary.common.enums.ProcessStepEnum;
import org.suwenqian.audiovideosummary.dao.entity.FileAsset;
import org.suwenqian.audiovideosummary.dao.entity.ProgressLog;
import org.suwenqian.audiovideosummary.dao.entity.Task;
import org.suwenqian.audiovideosummary.dao.mapper.FileAssetMapper;
import org.suwenqian.audiovideosummary.dao.mapper.TaskMapper;
import org.suwenqian.audiovideosummary.service.ProgressLogService;
import org.suwenqian.audiovideosummary.service.QiNiuUploadService;
import org.suwenqian.audiovideosummary.util.QiNiuUploaderUtil;
import org.suwenqian.audiovideosummary.util.VideoUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Date;
import java.util.Map;

import static org.suwenqian.audiovideosummary.common.constant.UploadReturnMapConstant.UPLOAD_Return_HASH_Object;
import static org.suwenqian.audiovideosummary.common.constant.UploadReturnMapConstant.UPLOAD_Return_KEY_Object;

@Service
@RequiredArgsConstructor
public class QiNiuUploadServiceImpl extends ServiceImpl<FileAssetMapper, FileAsset> implements QiNiuUploadService {

    private final FileAssetMapper fileAssetMapper;
    private final QiNiuUploaderUtil uploaderUtil;
    private final TransactionTemplate transactionTemplate;
    private final TaskMapper taskMapper;
    private final ProgressLogService progressLogService;


    @Override
    public String uploadQiNiu(MultipartFile file) throws IOException {
        Long taskId = cn.hutool.core.util.IdUtil.getSnowflakeNextId();
        // 1. 生成唯一 key
        String key = "raw/" + System.currentTimeMillis() + "/" + UUID.randomUUID() + ".mp4";

        // 2. 上传（>100 MB 走分片）
        Map<String, String> reMap;
        if (file.getSize() > 100 * 1024 * 1024) {
            Path temp = Files.createTempFile("su-wen-qia", ".tmp");
            file.transferTo(temp);
            reMap = uploaderUtil.uploadBigFile(temp, key);
            Files.deleteIfExists(temp);
        } else {
            reMap = uploaderUtil.uploadBytes(file.getBytes(), key);
        }

        // 3. 落库 file_asset
        Map<String, String> finalReMap = reMap;
        transactionTemplate.executeWithoutResult(status -> {
            try {
                FileAsset fileAsset = FileAsset.builder()
                        .id(cn.hutool.core.util.IdUtil.getSnowflakeNextId())
                        .taskId(taskId)
                        .type(file.getOriginalFilename())
                        .durationMs(VideoUtils.getVideoDuration(file))
                        .sizeByte(file.getSize())
                        .versionNo(1)
                        .kodoKey(finalReMap.get(UPLOAD_Return_KEY_Object))
                        .kodoHash(finalReMap.get(UPLOAD_Return_HASH_Object))
                        .createdAt(new Date())
                        .build();
                fileAssetMapper.insert(fileAsset);
            } catch (Exception e) {
                log.error("[音视频知识内容提取]--元数据写入数据库失败【】--{} -- 【】处理失败",e);
                status.setRollbackOnly();
            }
        });

        //4. 创建任务
        Task task = Task.builder()
                .id(taskId)
                .fileKey(reMap.get(UPLOAD_Return_KEY_Object))
                .fileName(file.getName())
                .status(2)
                .createdAt(new Date())
                .updatedAt(new Date())
                .build();
        taskMapper.insert(task);

        //5. 创建日志
        ProgressLog progressLog = ProgressLog.builder()
                .id(cn.hutool.core.util.IdUtil.getSnowflakeNextId())
                .step(ProcessStepEnum.UPLOAD)
                .taskId(taskId)
                .createdAt(new Date())
                .percent(ProcessStepEnum.UPLOAD.getPercent())
                .message(ProcessStepEnum.UPLOAD.getDescription())
                .build();
        progressLogService.sendProgress(progressLog);
        return reMap.get(UPLOAD_Return_KEY_Object);
    }
}
